﻿using System;
using System.Collections.Generic;
using UnityEngine;
using Extensions;
using UnityEditor;
using System.Reflection;

namespace TC
{
    //portsurface : surface {}
    
    public abstract class NodeComponentSurface : Surface
    {
        public NodeSurface parent;

        public abstract bool Contains(object obj); // 判断target是否被包含在node component中

        public abstract void SetPosition(Vector2 vec);

        public abstract PortSurface GetActiveMember();
    }
    
    public class SinglePortSurface<T> : NodeComponentSurface where T : Port
    {
        public T target;

        public SinglePortSurface(T target)
        {
            this.target = target;
        }

        public override bool Contains(object obj)
        {
            return target == (obj as T);
        }

        public override void SetPosition(Vector2 vec)
        {
            this.position = vec;
        }

        public override PortSurface GetActiveMember()
        {
            if (isContaining) { return this as PortSurface; }
            return null;
        }
    }

    // 带泛型：为了创建port时方便，泛型=port的类型
    public class PortGroupSurface<T> : NodeComponentSurface, IEntity<List<T>> where T : Port
    {
        public List<T> target { get; }
        public List<NodeComponentSurface> members = new List<NodeComponentSurface>();
        public bool isInput;
        private string targetName;
        private Color tmpColor;

        #region 名称
        private string showMsg { get => "Add " + targetName; }
        private GUIStyle _basicMsgStyle;
        private GUIStyle basicMsgStyle
        {
            get
            {
                if (_basicMsgStyle == default)
                {
                    _basicMsgStyle = new GUIStyle("label");
                    _basicMsgStyle.alignment = TextAnchor.MiddleCenter;
                    _basicMsgStyle.margin = new RectOffset(0, 0, 0, 0);
                    _basicMsgStyle.padding = new RectOffset(2, 2, 3, 3);
                    _basicMsgStyle.border = new RectOffset(0, 0, 0, 0);
                    _basicMsgStyle.fontSize = 12;
                    _basicMsgStyle.stretchWidth = false;
                    _basicMsgStyle.normal.textColor = EditorGUIUtility.isProSkin ? Color.white : Color.black;
                }
                return _basicMsgStyle;
            }
        }
        private GUIStyle msgStyle;
        private Vector2 msgSize;
        #endregion

        #region 加号
        private GUIStyle basicGizmosStyle = StyleProvider.PortGroupGizmos;
        private GUIStyle gizmosStyle;
        private Vector2 gizmosSize;
        #endregion

        #region 小组件整体
        private GUIStyle _basicBgStyle;
        private GUIStyle basicBgStyle
        {
            get
            {
                if (_basicBgStyle == default)
                {
                    _basicBgStyle = new GUIStyle("label");
                    _basicBgStyle.margin = new RectOffset(3, 3, 4, 4);
                    _basicBgStyle.padding = new RectOffset(0, 0, 0, 0);
                }
                return _basicBgStyle;
            }
            set { _basicBgStyle = value; }
        }
        private GUIStyle bgStyle;
        private Vector2 bgSize;
        private Vector2 bgPosition;
        private Rect bgRelativeRect;
        #endregion


        public PortGroupSurface(NodeSurface parent, List<T> target, float curScale, bool isInput, string name)
        {
            this.parent = parent;
            this.target = target;
            this.isInput = isInput;
            this.curScale = curScale;
            targetName = name;
            // TODO Group支持嵌套
            foreach (T port in target)
            {
                // TODO 后续修改，根据Port类型调用对应的构造器
                members.Add(new PortSurface(parent, port, curScale));
            }
        }


        #region 显示刷新

        public override void OnDraw(Rect nodeRect)
        {
            base.OnDraw(nodeRect);
            foreach (var member in members)
            {
                member.OnDraw(nodeRect);
            }

            relativeRect = GUIHelper.MarginBox(new Rect(nodeRect.position + bgPosition, bgSize), new GUIContent(""), bgStyle);
            GUILayout.BeginArea(relativeRect);
            tmpColor = GUI.color;
            GUI.color = StyleProvider.CustomElementColor;
            GUILayout.BeginHorizontal(StyleProvider.PortGroupBG);
            if (isInput)
            {
                GUILayout.Box("", gizmosStyle);
                GUI.color = tmpColor;
                GUILayout.Box(showMsg, msgStyle);
            }
            else
            {
                GUI.color = tmpColor;
                GUILayout.Box(showMsg, msgStyle);
                tmpColor = GUI.color;
                GUI.color = StyleProvider.CustomElementColor;
                GUILayout.Box("", gizmosStyle);
                GUI.color = tmpColor;
            }
            GUILayout.EndHorizontal();
            GUILayout.EndArea();

            tmpColor = GUI.color;
            GUI.color = Color.white;
            GUI.color = tmpColor;

            if (isHovering)
            {
                EditorGUIUtility.AddCursorRect(relativeRect, MouseCursor.ArrowPlus);
            }
        }

        public override void RefreshScale(float newScale, Vector2 mousePosition)
        {
            foreach (var member in members) { member.RefreshScale(newScale, mousePosition); }
            base.RefreshScale(newScale, mousePosition);
        }

        public override void RefreshStyle()
        {
            foreach (var member in members) { member.RefreshStyle(); }

            msgStyle = new GUIStyle(basicMsgStyle);
            msgStyle.fontSize = (int)Mathf.Floor(basicMsgStyle.fontSize * curScale / maxScale);
            if (msgStyle.fontSize <= 0) { msgStyle.fontSize = 1; }
            msgStyle.padding = basicMsgStyle.padding.Multiply(curScale / maxScale);
            msgStyle.margin = basicMsgStyle.margin.Multiply(curScale / maxScale);

            gizmosStyle = new GUIStyle(basicGizmosStyle);
            gizmosStyle.padding = basicGizmosStyle.padding.Multiply(curScale / maxScale);
            gizmosStyle.margin = basicGizmosStyle.margin.Multiply(curScale / maxScale);
            gizmosStyle.fixedWidth = basicGizmosStyle.fixedWidth * curScale / maxScale;
            gizmosStyle.fixedHeight = basicGizmosStyle.fixedHeight * curScale / maxScale;

            bgStyle = new GUIStyle(basicBgStyle);
            bgStyle.padding = basicBgStyle.padding.Multiply(curScale / maxScale);
            bgStyle.margin = basicBgStyle.margin.Multiply(curScale / maxScale);
        }

        public override void RefreshSize()
        {
            foreach (var member in members) { member.RefreshSize(); }

            msgSize = msgStyle.CalFullSize(showMsg);
            gizmosSize = new Vector2(gizmosStyle.fixedWidth, gizmosStyle.fixedHeight);

            Vector2 contentSize = new Vector2(msgSize.x + gizmosSize.x,
                     (msgSize.y > gizmosSize.y) ? msgSize.y : gizmosSize.y);
            bgSize = bgStyle.CalBoundSize(contentSize);

            // 整体size
            size = Vector2.zero;
            foreach (var member in members)
            {
                size.y += member.size.y;
                size.x = (size.x < member.size.x) ? member.size.x : size.x;
            }
            size.y += bgSize.y;
            size.x = (size.x < bgSize.x) ? bgSize.x : size.x;
        }

        #endregion

        #region 事件处理

        public override void ChildrenEventHandler()
        {
            foreach (var member in members)
            {
                member.OnEvent();
            }
        }

        public override void MouseDownEventHandler()
        {
            base.MouseDownEventHandler();
            if (isContaining) { Event.current.Use(); }
        }

        public override void MouseUpEventHandler()
        {
            if (isContaining)
            {
                CreateMember();
                Event.current.Use();
            }
        }

        #endregion

        #region 成员相关

        public override bool Contains(object obj)
        {
            foreach (T item in target)
            {
                if (item == (obj as T)) { return true; }
            }
            return false;
        }

        public override void SetPosition(Vector2 vec)
        {
            position = new Vector2(vec.x, vec.y);
            if (isInput)
            {
                foreach (var member in members)
                {
                    member.SetPosition(vec);
                    vec.y += member.size.y;
                }
                bgPosition = new Vector2(vec.x, vec.y);
            }
            else
            {
                vec.x += size.x;
                foreach (var member in members)
                {
                    member.SetPosition(new Vector2(vec.x - member.size.x, vec.y));
                    vec.y += member.size.y;
                }
                bgPosition = new Vector2(vec.x - bgSize.x, vec.y);
            }
        }

        private void CreateMember()
        {
            if ((parent as FlowNodeSurface) != null)
            {
                Port port = (parent as FlowNodeSurface).target.AddPort(typeof(T), targetName + target.Count);
                target.Add(port as T);
                members.Add(new PortSurface(parent, port, curScale));
                (parent as FlowNodeSurface).RefreshAppearance();
            }
            // TODO 扩展行为树节点处理部分
        }

        public override PortSurface GetActiveMember()
        {
            foreach (var member in members)
            {
                if ((member as PortSurface).isContaining)
                { return member as PortSurface; }
            }
            return null;
        }

        #endregion

        #region 序列化
        #endregion

    }
}
